//
//  ZSViewController.m
//  加载网络图片
//
//  Created by @Zs on 15/8/30.
//  Copyright (c) 2015年 @Zs. All rights reserved.
//

#import "ZSViewController.h"
#import "HMApps.h"
@interface ZSViewController ()
//应用程序列表
@property (nonatomic,strong) NSArray *appList;
//统一加载所有下载操作队列
@property(nonatomic,strong)NSOperationQueue *opQueue;
//缓存
@property(nonatomic,strong)NSMutableDictionary *opCacheDict;
@end

@implementation ZSViewController


-(NSMutableDictionary *)opCache{

    if (_opCacheDict == nil) {
        _opCacheDict = [NSMutableDictionary dictionary];
    }
    
    return _opCacheDict;
}


-(NSOperationQueue *)opQueue{
    if (_opQueue == nil) {
        _opQueue = [[NSOperationQueue alloc]init];
    }
    
    return _opQueue;
}


-(NSArray *)appList{

    if (_appList == nil) {
        
        NSURL *url = [[NSBundle mainBundle] URLForResource:@"apps.plist" withExtension:nil];
        
        NSArray *array = [NSArray arrayWithContentsOfURL:url];
        
        //字典转模型
        NSMutableArray *arrayM = [NSMutableArray array];
        for (NSDictionary *dict in array) {
            [arrayM addObject:[HMApps appsWithDict:dict]];
        }
        
        _appList = arrayM;
    }
    return  _appList;
    
}

#pragma mark 表格数据源
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
    return self.appList.count;
}


/**
    同步加载图片的问题
    1.如果网络速度不好,网络问题会导致加载出现卡顿
      解决方法,使用多线程异步加载图片,加载完成后,刷新表格
        
    新问题:
 
    1.1
        图像默认不显示,需要滚动刷新之后才显示
       解决办法:
        使用占位图像
    
    1.2
         如果表格滚动的快,网络下载来不及更新,会出现多个下载完成后,更新同一个cell的情况
         cell的重用问题
        解决办法:
         MVC的目的是让数据和界面分离,数据由模型来处理,界面只是显示数据,考虑将网络下载得到得图片放到模型中,下载完成之后,直接刷新cell
 
    2.每次都要从网上加载图片,消耗用户的流量
        下载完成的图片保存在模型中,在显示表格的时候,判断如果有图片就不再进行下载
    3.如果图片下载时间较长,并且用户频繁滚动表格会怎样==>同一个下载任务会被下载多次
        解决办法:
         给下载任务做一个缓存!使用一个字典记录所有的下载操作
         当再次请求下载图片时,首先判断是否有该图片的下载操作,如果有,说明正在下载,就不再下载
    4.下载完成之后,操作缓存字典的操作,还有必要保存吗
 
 */
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *ID = @"AppCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
    
    //取出模型
    HMApps *app = self.appList[indexPath.row];
    
    cell.textLabel.text = app.name;
    cell.detailTextLabel.text = app.download;
    
    //判断沙盒中是否有图像,如果有就直接显示
    NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];

    cacheDir = [cacheDir stringByAppendingPathComponent:[app.icon lastPathComponent]];
    
    NSLog(@"cacheDir -%@",cacheDir);
    //从沙盒中直接加载图像
    UIImage *image =[UIImage imageWithContentsOfFile:cacheDir];
    
    //如果沙盒中有图像,直接显示图像
    if (image) {
        NSLog(@"从模型中显示图像,没有连接网络");
        cell.imageView.image = image;
    }else{
        //模型中没有图像,需要下载
        //给cell设置占位图像
        cell.imageView.image = [UIImage imageNamed:@"user_default"];
        
        [self downloadWithIndexPath:indexPath];
        
        
    }
    return cell;
}
/**
 *
    代码重构:
    1.新建方法
    2.将代码复制到新方法中
    3.根据代码需要调整参数
    
    在开发中,应避免过多的分支嵌套
 */
-(void)downloadWithIndexPath:(NSIndexPath *)indexPath{
    
    //获取模型
    HMApps *app = self.appList[indexPath.row];

    //0.从操作字典中根据图片的url取出下载操作,如果存在说明正在下载中
    NSBlockOperation *downloadOp = self.opCacheDict[app.icon];
    
    if (downloadOp != nil) {
        //说明已经在下载中
        return;
    }
    
    
    /**Block中要注意self的循环引用
     * 循环引用的判断用dealloc
     */
    
    
    __weak ZSViewController *weakSelf = self;
    //还没有开始下载操作
    //1.实例化操作
    downloadOp = [NSBlockOperation blockOperationWithBlock:^{
    //使用URL直接加载网络图片
    //所有的网络图片传输都是二进制数据
    
    //模拟网络卡顿
    [NSThread sleepForTimeInterval:0.5f];
    
    NSData *data = [NSData dataWithContentsOfURL: [NSURL URLWithString:app.icon]];
    UIImage *image = [UIImage imageWithData:data];
    
    //将图片保存在Cache目录中
        NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
        //lastPathComponent 从路径中取出最后的组成部分,通常就是文件名
        cacheDir = [cacheDir stringByAppendingPathComponent:[app.icon lastPathComponent]];
    
    
    NSLog(@"下载完成 ");
   //将数据保存在沙盒中
        [data writeToFile:cacheDir atomically:YES];
        
        
        
    //在主线程更新UI
    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
        //将下载操作从缓存字典中删除,避免随着网络图片的增加字典越来越大,如果下载失败,会再次刷新重新下载
        [weakSelf.opCacheDict removeObjectForKey:app.icon];
        
        
        //出现第一次加载不出现图片 点击才有 刷新才有  是因为第一次刷新表格的时候,返回的cell表格中是没有ImageView的
        //图片已经存在但是xy宽高都是0 ,当再次设置图像的时候,默认的TableViewCell会根据Image的大小,自动调整UIImageView的尺寸
        //                    cell.imageView.image = image;
        //给模型设置image属性
        app.image = image;
        
        //刷新表格
        [weakSelf.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
        }];

    }];
    //2.将操作添加到队列

    [self.opQueue addOperation:downloadOp];

    //3.将操作添加到缓存字典,可以使用图像下载的URL做为键值对(即使两行使用的同一个图片也只下载一次)
    [self.opCacheDict setObject:downloadOp forKey:app.icon];

    NSLog(@"当前的下载任务数量 :  %zd",self.opCacheDict.count);
    
}

-(void)dealloc{
    NSLog(@"我走了!!!!");
}

@end
